const PENGING = 'pending';//等待
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected'; //失败
class MyPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject)//执行器会立即执行
        } catch (error) {
            this.reject(error)
        }
       
    }
    status = PENGING
    //   成功的值
    value = undefined
    //  失败的值
    reason = undefined
    successCallBack = []
    failCallBack = []
    resolve = value => {
        //   如果状态不是等待，阻止程序向下执行
        if (this.status !== PENGING) return
        //   将状态更改成功
        this.status = FULFILLED
        // 保存成功后的值
        this.value = value
        // 判断成功回调是否存在，如果存在就调用
        // this.successCallBack && this.successCallBack(this.value)
        while (this.successCallBack.length) {
            this.successCallBack.shift()()
        }

    }
    reject = reason => {
        if (this.status !== PENGING) return
        //   将状态改为失败
        this.status = REJECTED
        //   保存失败的原因
        this.reason = reason
        // 判断失败回调是否存在，如果存在就调用
        // this.failCallBack && this.failCallBack(this.reason)
        while (this.failCallBack.length) {
            this.failCallBack.shift()()
        }
    }
    then(successCallBack, failCallBack) {
        successCallBack = successCallBack?successCallBack:value=>value
        failCallBack = failCallBack?failCallBack:reason=>{throw reason} 
        let promise2 = new MyPromise((resolve, reject) => {
            //   判断状态
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = successCallBack(this.value)
                        //   判断x是普通值还是promise对象
                        // 如果是普通值 直接调用resolve
                        // 如果是promise对象 查看promise对象返回的结果
                        // 再根据promise对象返回的结果决定用resolve还是reject
                        resovlePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                   
                    // resolve(x)
                }, 0)

          
            } else if (this.status === REJECTED) {
                
                setTimeout(() => {
                    try {
                        let x =failCallBack(this.reason)
                        //   判断x是普通值还是promise对象
                        // 如果是普通值 直接调用resolve
                        // 如果是promise对象 查看promise对象返回的结果
                        // 再根据promise对象返回的结果决定用resolve还是reject
                        resovlePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                   
                    // resolve(x)
                }, 0)
            } else {
                // 等待
                // 将成功回调和失败回调存储
                this.successCallBack.push(()=>{
                    setTimeout(() => {
                        try {
                            let x = successCallBack(this.value)
                            //   判断x是普通值还是promise对象
                            // 如果是普通值 直接调用resolve
                            // 如果是promise对象 查看promise对象返回的结果
                            // 再根据promise对象返回的结果决定用resolve还是reject
                            resovlePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                       
                        // resolve(x)
                    }, 0)
                })
                this.failCallBack.push(()=>{
                    setTimeout(() => {
                        try {
                            let x =failCallBack(this.reason)
                            //   判断x是普通值还是promise对象
                            // 如果是普通值 直接调用resolve
                            // 如果是promise对象 查看promise对象返回的结果
                            // 再根据promise对象返回的结果决定用resolve还是reject
                            resovlePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                       
                        // resolve(x)
                    }, 0)
                })
            }
        })

        return promise2
    }
    finally(callback){
       return this.then(value=>{
           return MyPromise.resolve(callback()).then(()=>value)
        },reason=>{
            callback()
            throw reason
        })
    }
    catch(failCallBack){
       return this.then(undefined,failCallBack)
    }
    static all(arr){
        let result = []
        let index = 0
        
        return new MyPromise((resolve,reject)=>{
            function addData(key,value){
                result[key] = value
                index ++
                if(index === arr.length){
                    resolve(result)
                }
            }
            for(let i = 0;i<arr.length;i++){
                let current = arr[i]
                if(current instanceof MyPromise){
                    // promise对象
                    current.then(value=>addData(i,value),(reason)=>{reject(reason)})
                }else{
                    // 普通值
                    addData(i,arr[i])
                }
            }
        } )
    }
    static resolve(value){
        if(value instanceof MyPromise) return value
        return new MyPromise (resolve=> resolve(value))
    }
}
function resovlePromise(promise2, x, resolve, rejected) {
    if (promise2 === x) {
        return rejected(new TypeError('Chanining cycle deteced for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // promise对象
        // x.then(value=>resolve(value),reason=>rejected(reason))
        x.then(resolve, rejected)
    } else {
        resolve(x)
    }
}
module.exports = MyPromise